package net.uzen.office.article;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilderFactory;

import net.uzen.office.article.model.Article;
import net.uzen.office.article.service.ArticleService;
import net.uzen.office.attached.model.Attached;
import net.uzen.office.common.UzenOfficeConstants;
import net.uzen.office.common.controller.BaseController;
import net.uzen.office.common.model.SessionInfo;
import net.uzen.office.common.util.SessionUtil;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class ArticleController extends BaseController {

	private static final Log logger = LogFactory
			.getLog(ArticleController.class);

	private ArticleService articleService;

	public void setArticleService(ArticleService articleService) {
		this.articleService = articleService;
	}

	public ModelAndView list(HttpServletRequest request,
			HttpServletResponse response, Article article) {

		// TODO : Validation
		// 검색할 것을 대비 하여 Validation 을 해야한다.
		List<Article> articleList = articleService.getArticleList(article);

		ModelAndView mav = new ModelAndView();
		mav.addObject("articleList", articleList);
		mav.addObject("boardNo", article.getBoardNo());
		
		return mav;
	}

	public ModelAndView read(HttpServletRequest request,
			HttpServletResponse response, Article article) {

		// TODO : Validation

		Map<String, Object> resultMap = articleService.getArticle(article);
		if (resultMap.get("article") == null) {
			// TODO : 에러 처리
		}

		logger.debug("[!] attachedList.size : "
				+ ((ArrayList<Attached>) resultMap.get("attachedList")).size());

		ModelAndView mav = new ModelAndView();
		mav.addAllObjects(resultMap);

		return mav;
	}

	public ModelAndView createForm(HttpServletRequest request,
			HttpServletResponse response, Article article) {

		ModelAndView mav = new ModelAndView();
		mav.addObject("article", article);
		
		

		return mav;
	}

	public ModelAndView create(HttpServletRequest request,
			HttpServletResponse response, Article article) throws Exception {

		// TODO : Validation

		if (StringUtils.isNotEmpty(article.getAttachedFile()
				.getOriginalFilename())) {
			// 파일에 관해 시험
			MultipartFile temp = article.getAttachedFile();
			logger.debug("[!] filename : " + temp.getName());
			logger.debug("[!] orignal Name : " + temp.getOriginalFilename());
			logger.debug("[!] fileSize : " + temp.getSize());

			// 파일 저장소
			File destinationDir = new File(UzenOfficeConstants.FILE_REPOSITORY);
			File destination = File.createTempFile(
					UzenOfficeConstants.FILENAME_PREFIX, temp
							.getOriginalFilename(), destinationDir);
			FileCopyUtils.copy(temp.getInputStream(), new FileOutputStream(
					destination));

			logger.debug("[!] destination : " + destination.getAbsolutePath());
			logger.debug("[!] destination : " + destination.getName());
			logger.debug("[!] destination : " + destination.getAbsoluteFile());

			// 업로드한 파일 이름 설정
			article.setAttachedFilename(destination.getAbsolutePath());
		}

		// 등록 기본 정보를 셋팅한다.
		BeanUtils.copyProperties(SessionUtil.getSessionInfoBase(request),
				article);

		// Article 정보를 등록한다.
		int articleNo = articleService.createArticle(article);

		if (articleNo == 0) {
			// TODO: 에러 처리
		}

		Article paramArticle = new Article();
		paramArticle.setArticleNo(articleNo);
		paramArticle.setBoardNo(article.getBoardNo());

		Map<String, Integer> paramMap = new HashMap<String, Integer>();
		paramMap.put("articleNo", articleNo);
		paramMap.put("boardNo", article.getBoardNo());

		return new ModelAndView("redirect:/article/read.jude", paramMap);
	}

	public ModelAndView modifyForm(HttpServletRequest request,
			HttpServletResponse response, Article article) {
		// SessionUtil 에 어드민인지 확인하는거 추가
		// Admin 인지 아닌지 확인하고 Admin 인 경우 Admin 으로 셋팅한다.

		// 수정 폼 출력이 가능한 경우
		// 1. 레코드 등록자와 로그 인 사용자가 같을 때
		// 2. 로그 인 사용자가 관리자일 때
		SessionInfo si = SessionUtil.getSession(request);
		article.setCreatorNo(si.getMemberNo());

		if (article.getCreatorNo() != si.getMemberNo()
				&& !SessionUtil.isAdminSession(request)) {
			article.setAuthorized(false);
		}

		// Article article2Modify = articleService.getArticle(article);
		//
		// if (article2Modify == null) {
		// // 수정 폼에 넣을 데이터를 가져올 수 없다. 즉, 수정 권한이 없다.
		// // TODO : 에러처리
		// }

		ModelAndView mav = new ModelAndView();
		// mav.addObject("article", article2Modify);

		return mav;
	}

	public ModelAndView modify(HttpServletRequest request,
			HttpServletResponse response, Article article) {

		// TODO : Validation

		// 수정이 가능한 경우
		// 1. 레코드 등록자와 로그 인 사용자가 같을 때
		// 2. 로그 인 사용자가 관리자일 때
		SessionInfo si = SessionUtil.getSessionInfo(request);
		article.setCreatorNo(si.getMemberNo());
		article.setModifierNo(si.getMemberNo());

		if (article.getCreatorNo() != si.getMemberNo()
				&& !SessionUtil.isAdminSession(request)) {
			article.setAuthorized(false);
		}

		// Article 정보를 수정한다.
		if (!articleService.modifyArticle(article)) {
			// TODO : 에러 처리
		}

		Map<String, Integer> paramMap = new HashMap<String, Integer>();
		paramMap.put("articleNo", article.getArticleNo());
		paramMap.put("boardNo", article.getBoardNo());

		return new ModelAndView("redirect:/article/read.jude", paramMap);
	}

	public ModelAndView delete(HttpServletRequest request,
			HttpServletResponse response, Article article) {

		// TODO : Validation

		if (!articleService.deleteArticle(article)) {
			// TODO : 에러 처리
		}

		return new ModelAndView("redirect:/article/list.jude", "boardNo",
				article.getBoardNo());
	}

	public ModelAndView replyForm(HttpServletRequest request,
			HttpServletResponse response, Article article) {

		ModelAndView mav = new ModelAndView();
		mav.addObject("article", article);

		return mav;
	}

	public ModelAndView reply(HttpServletRequest request,
			HttpServletResponse response, Article article) {

		// TODO : Validation
		// 등록 기본 정보를 셋팅한다.
		SessionInfo si = SessionUtil.getSessionInfo(request);
		article.setCreatorNo(si.getMemberNo());
		article.setModifierNo(si.getMemberNo());

		// Article 정보를 등록한다.
		int articleNo = articleService.replyArticle(article);

		if (articleNo == 0) {
			// TODO: 에러 처리
		}

		Map<String, Integer> paramMap = new HashMap<String, Integer>();
		paramMap.put("articleNo", articleNo);
		paramMap.put("boardNo", article.getBoardNo());

		return new ModelAndView("redirect:/article/read.jude", paramMap);
	}

	public ModelAndView form(HttpServletRequest request,
			HttpServletResponse response, Article article) {

		ModelAndView mav = new ModelAndView();
		mav.addObject("article", article);

		// 수정 폼일 경우 내용을 가져와서 출력한다.
		if (UzenOfficeConstants.FORM_MODE_MODIFY.equals(article.getMode())) {
			// 수정 폼은 출력이 가능한 경우에만 출력한다.
			// 1. 레코드 등록자와 로그 인 사용자가 같을 때
			// 2. 로그 인 사용자가 관리자일 때
			SessionInfo si = SessionUtil.getSession(request);
			article.setCreatorNo(si.getMemberNo());

			if (article.getCreatorNo() != si.getMemberNo()
					&& !SessionUtil.isAdminSession(request)) {
				article.setAuthorized(false);
			}

			Map<String, Object> resultMap = articleService.getArticle(article);

			if (resultMap.get("article") == null) {
				// 수정 폼에 넣을 데이터를 가져올 수 없다. 즉, 수정 권한이 없다.
				// TODO : 에러처리
			}

			mav.addObject(resultMap);
		}

		return mav;
	}

	public ModelAndView test(HttpServletRequest request,
			HttpServletResponse response) {

		return new ModelAndView();
	}

	public ModelAndView uploadPhoto(HttpServletRequest request,
			HttpServletResponse response, Article article) {
		// http://api.flickr.com/services/rest/?api_key=03f3fab85e2cd28de1fb969b320768bc&method=flickr.photos.getSizes&photo_id=4175667707
		String API_KEY = "03f3fab85e2cd28de1fb969b320768bc";
		String SECRET = "8c7381558956a210";
		String PERMS = "write";

		String url = null;

		try {
			String API_SIG = SECRET + "api_key" + API_KEY + "perms" + PERMS;

			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(API_SIG.getBytes());
			byte[] digested = md.digest();

			StringBuilder hexString = new StringBuilder();
			for (int i = 0; i < digested.length; i++) {
				logger.debug("[!] < " + i + " > : " + digested[i] + " >> "
						+ (0xFF & digested[i]) + " >>> "
						+ Integer.toHexString(0xFF & digested[i]));
				hexString.append(Integer.toHexString(0xFF & digested[i])
						.length() == 0 ? 00 : Integer.toHexString(
						0xFF & digested[i]).length() == 1 ? "0"
						+ Integer.toHexString(0xFF & digested[i]) : Integer
						.toHexString(0xFF & digested[i]));
			}

			url = "http://flickr.com/services/auth/?api_key=" + API_KEY
					+ "&perms=" + PERMS + "&api_sig=" + hexString.toString();
			logger.debug(" >> URL : " + url);

			HttpClient httpClient = new HttpClient();
			httpClient.getParams().setParameter(
					"http.protocol.element-charset", "UTF-8");
			httpClient.getParams().setParameter(
					"http.protocol.content-charset", "UTF-8");

			logger.debug(" >> httpClient : "
					+ httpClient.getParams().getParameter(
							"http.protocol.element-charset"));

			GetMethod getMethod = new GetMethod(url);

			logger.debug(" >> creating getMethod");
			int result = httpClient.executeMethod(getMethod);

			// Get the response body
			InputStream rstream = getMethod.getResponseBodyAsStream();
			logger.debug(" >> creating rstream");
			Document responseD = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder().parse(rstream);

			logger.debug(" >> creating responseD");
			String frob = null;

			NodeList frobResponse = responseD.getElementsByTagName("frob");
			logger.debug(" >> creating nodeList");
			Node frobNode = frobResponse.item(0);
			if (frobNode != null) {
				frob = frobResponse.item(0).getTextContent();
				System.out.println("Successfully retrieved frob: " + frob);
			} else {
				logger.error(responseD);
			}

			// logger.debug(" >> result : " + result);
			// if (result > 0) {
			// logger.debug(" >> Response : "
			// + getMethod.getResponseBodyAsString());
			// InputStream rstream = getMethod.getResponseBodyAsStream();
			//				
			// logger.debug(" >> creating rstream : " + rstream);
			//				
			// Document responseD = DocumentBuilderFactory.newInstance()
			// .newDocumentBuilder().parse(rstream);
			//
			// logger.debug(" >> creating responseD : " + responseD);
			// logger.debug(" >> creating responseD : " + responseD.toString());
			// String frob = null;
			//				
			// NodeList frobResponse = responseD.getElementsByTagName("frob");
			// logger.debug(" >> creating nodeList");
			// Node frobNode = frobResponse.item(0);
			// if (frobNode != null) {
			// frob = frobResponse.item(0).getTextContent();
			// System.out.println("Successfully retrieved frob: " + frob);
			// } else {
			// logger.error(responseD);
			// }
			// }

		} catch (Exception e) {
			logger.error(e);
		}
		return new ModelAndView();
	}

	public ModelAndView uploadPhoto2(HttpServletRequest request,
			HttpServletResponse response, Article article) {
		// API 키 값들
		String API_KEY = "03f3fab85e2cd28de1fb969b320768bc";
		String SECRET = "8c7381558956a210";
		String PERMS = "write";
		String METHOD = "flickr.auth.getFrob";

		String apiSig = SECRET + "api_key" + API_KEY + "method" + METHOD
				+ "perms" + PERMS;

		String hexString = getMD5Hash(apiSig);

		// URL 셋팅
		String url = "http://flickr.com/services/rest/?api_key=" + API_KEY
				+ "&method=" + METHOD + "&api_sig=" + hexString + "&perms="
				+ PERMS;

		// HttpClient 설정
		HttpClient httpClient = new HttpClient();
		httpClient.getParams().setParameter("http.protocol.element-charset",
				"UTF-8");
		httpClient.getParams().setParameter("http.protocol.content-charset",
				"UTF-8");

		// GetMethod 설정
		GetMethod getMethod = new GetMethod(url);

		try {
			// HttpClient 를 통해 GetMethod 를 실행
			int result = httpClient.executeMethod(getMethod);

			// TODO : HttpStatus 를 비교
			if (result > 0) {

				// Get the response body
				InputStream rstream = getMethod.getResponseBodyAsStream();

				// Document 구조로 읽어와 원하는 노드를 찾기 위해 Parsing
				Document responseD = DocumentBuilderFactory.newInstance()
						.newDocumentBuilder().parse(rstream);
				NodeList frobResponse = responseD.getElementsByTagName("frob");

				// Token을 가져오기 위한 frob 값 선언
				String frob = null;

				// frob 태그 안의 값을 가져온다.
				Node frobNode = frobResponse.item(0);

				// frob 노드가 null 이 아닐 경우에
				if (frobNode != null) {
					// frob 에 값을 셋팅한다.
					frob = frobResponse.item(0).getTextContent();
					logger.debug("[!] Successfully retrieved frob: " + frob);

					// frob 를 토큰으로 바꿔오는 작업
					String METHOD_CONVERT = "flickr.auth.getToken";
					apiSig = SECRET + "api_key" + API_KEY + "frob" + frob
							+ "method" + METHOD_CONVERT;

					// URL 셋팅
					url = "http://flickr.com/services/rest/?method="
							+ METHOD_CONVERT + "&api_key=" + API_KEY + "&frob="
							+ frob + "&api_sig=" + getMD5Hash(apiSig);
					logger.debug("[!!] URL >> " + url);

					// GetMethod 설정
					getMethod = new GetMethod(url);

					// HttpClient 를 통해 GetMethod 를 실행
					result = httpClient.executeMethod(getMethod);

					// TODO : HttpStatus 를 비교
					if (result > 0) {

						// Get the response body
						rstream = getMethod.getResponseBodyAsStream();
						logger.debug(" >> getResponseBodyAsString() > "
								+ getMethod.getResponseBodyAsString());
						logger.debug("[!] rstream >> " + rstream);

						// Document 구조로 읽어와 원하는 노드를 찾기 위해 Parsing
						responseD = DocumentBuilderFactory.newInstance()
								.newDocumentBuilder().parse(rstream);
						NodeList tokenResponse = responseD
								.getElementsByTagName("token");

						// authorizaion 가져오기 위한 token 값 선언
						String token = null;

						// token 태그 안의 값을 가져온다.
						Node tokenNode = frobResponse.item(0);
						// token 노드가 null 이 아닐 경우에
						if (tokenNode != null) {
							// frob 에 값을 셋팅한다.
							token = tokenResponse.item(0).getTextContent();
							logger.debug("[!] Successfully retrieved token : "
									+ token);
						}
					}
				} else {
					logger.error(responseD);
				}
			}
		} catch (Exception e) {
			logger.error(e);
		}

		return new ModelAndView();
	}

	private String getMD5Hash(String string) {
		StringBuilder hexString = new StringBuilder();
		try {
			// MD5 해시 값 가져오기
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(string.getBytes());
			byte[] digested = md.digest();

			// byte[] to Hex
			for (int i = 0; i < digested.length; i++) {
				hexString.append(Integer.toHexString(0xFF & digested[i])
						.length() == 0 ? 00 : Integer.toHexString(
						0xFF & digested[i]).length() == 1 ? "0"
						+ Integer.toHexString(0xFF & digested[i]) : Integer
						.toHexString(0xFF & digested[i]));
			}
		} catch (Exception e) {
			logger.error(e);
		}
		return hexString.toString();
	}

	public void test2(HttpServletRequest request, HttpServletResponse response) {
		logger.debug(" >> [!] test2.jude");

		// API 키 값들
		String API_KEY = "03f3fab85e2cd28de1fb969b320768bc";
		String SECRET = "8c7381558956a210";
		String PERMS = "write";
		String METHOD = "flickr.auth.getFrob";

		String apiSig = SECRET + "api_key" + API_KEY + "perms" + PERMS;

		// URL 셋팅
		String url = "http://flickr.com/services/auth/?api_key=" + API_KEY
				+ "&perms=" + PERMS + "&api_sig=" + getMD5Hash(apiSig);

		logger.debug(" >> [!] URL : " + url);		
		
		// HttpClient 설정
		HttpClient httpClient = new HttpClient();
		httpClient.getParams().setParameter("http.protocol.element-charset",
				"UTF-8");
		httpClient.getParams().setParameter("http.protocol.content-charset",
				"UTF-8");

		// GetMethod 설정
		GetMethod getMethod = new GetMethod(url);

		try {
			// HttpClient 를 통해 GetMethod 를 실행
			int result = httpClient.executeMethod(getMethod);

			// TODO : HttpStatus 를 비교
			if (result > 0) {
				// Get the response body
				InputStream rstream = getMethod.getResponseBodyAsStream();

				// Document 구조로 읽어와 원하는 노드를 찾기 위해 Parsing
				Document responseD = DocumentBuilderFactory.newInstance()
						.newDocumentBuilder().parse(rstream);
				NodeList frobResponse = responseD.getElementsByTagName("frob");

				// frob 태그 안의 값을 가져온다.
				Node frobNode = frobResponse.item(0);

				// frob 노드가 null 이 아닐 경우에
				if (frobNode != null) {
					// frob 에 값을 셋팅한다.
					response.setContentType("text/plain; charset=UTF-8");
					response.getOutputStream().write(frobResponse.item(0).getTextContent().getBytes());
				}
				
			}
		} catch(Exception e) {
			logger.error(e);
		}

//				// Get the response body
//				InputStream rstream = getMethod.getResponseBodyAsStream();
//
//				// Document 구조로 읽어와 원하는 노드를 찾기 위해 Parsing
//				Document responseD = DocumentBuilderFactory.newInstance()
//						.newDocumentBuilder().parse(rstream);
//				NodeList frobResponse = responseD.getElementsByTagName("frob");
//
//				// Token을 가져오기 위한 frob 값 선언
//				String frob = null;
//
//				// frob 태그 안의 값을 가져온다.
//				Node frobNode = frobResponse.item(0);
//
//				// frob 노드가 null 이 아닐 경우에
//				if (frobNode != null) {
//					// frob 에 값을 셋팅한다.
//					frob = frobResponse.item(0).getTextContent();
//					logger.debug("[!] Successfully retrieved frob: " + frob);
	}
	
	public void getAuth(HttpServletRequest request, HttpServletResponse response) {
		logger.debug(" >> [!] getAuth.jude");

		// API 키 값들
		String API_KEY = "03f3fab85e2cd28de1fb969b320768bc";
		String SECRET = "8c7381558956a210";
		String PERMS = "write";
		String METHOD = "flickr.auth.getToken";
		String frob = request.getParameter("frob");
		
		// frob 를 토큰으로 바꿔오는 작업
		String apiSig = SECRET + "api_key" + API_KEY + "frob" + frob
				+ "method" + METHOD;

		logger.debug(" >> [!] apiSig : " + apiSig);
		
		// URL 셋팅
		String url = "http://flickr.com/services/rest/?api_key=" + API_KEY + "&frob="
				+ frob + "&method=" + METHOD + "&api_sig=" + getMD5Hash(apiSig);
		logger.debug("[!!] URL >> " + url);

		try {
			response.setContentType("text/plain; charset=UTF-8");
			response.getOutputStream().write(url.getBytes());
		} catch (Exception e) {
			
		}
	}
	
}
